package threads;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Observable;

import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;

import data.Page;
import data.STATUS;

/**
 * @author Gavin Greene
 * @author Dan Dalton
 *
 * After being constructed with a URL, this class Parses the URl, and makes the following available via class methods: 
 * 
 * URLs
 * Words
 */
public class Parser extends Observable implements Runnable, Comparable {
	/**
	 * Page that will be parsed.
	 */
	private final Page my_page;
	/**
	 * The resulting document from parsing this page.
	 */
	private final Document my_doc;
	/**
	 * All the available words from my Page.
	 */
	private List<String> my_words;
	/**
	 * All the available URL's from my Page.
	 */
	private final List<String> my_urls;

	/***
	 * Parses the page using the document found in the page.
	 * @param the_page to be parsed.
	 */
	public Parser(final Page the_page) {
		my_page = the_page;
		my_doc = my_page.getDoc();
		my_urls = new ArrayList<String>();
		my_words = new ArrayList<String>();
	}

	/**
	 * Parses a Document into Words and URLs 
	 */
	@Override
	public void run() {
		final long start = System.currentTimeMillis();
		// get links
		Elements links = my_doc.select("a[href]");
		for (Element link : links) {
			my_urls.add(link.attr("abs:href"));
		}
		// get words
		String doc_text = my_doc.text();
		String[] words = doc_text.split("\\s+");
		//todo: replace with regex
		//String[] words = doc_text.split("w\\s+");
		for (String word : words){
			String[] split = word.split("[\\.,?!]");
			try{
				my_words.add(split[0].toLowerCase());
			} catch  (Exception e){
				// The only way this array would be empty is if the word contained ONLY a .,?! and no other symbols/letters...
				// Skip this 'word' since its really only punctuation... 
			}
		}
		final long end = System.currentTimeMillis();
		final long runtime = end - start;
		
		// Updating Status with the words, URLs, and runtime.
		my_page.setStatus(STATUS.PARSED, my_words, my_urls, runtime);
		finish();
	}
	/**
	 * Announce to the world that you finished like a champ.
	 */
	private void finish(){
		this.setChanged();
		this.notifyObservers(my_page);
	}
	
	/**
	 * Gets the page.
	 * @return the page I'm working on.
	 */
	public Page getPage(){
		return my_page;
	}

	@Override
	public int compareTo(Object o) {
		//TODO: For some reason the TPE throws a fit if these aren't comparable?
		// This horrible workaround seems to have no negative effect... 
		return 1;
	}
	
}
